#include "Logger.h"
#include <Windows.h>
#include "resource.h"
#include "CaelumInternal.h"
#include <sstream>

namespace Caelum {

	/*
	 *
	 * TODO: ADD EVENT HANDLING
	 *
	 */

void Logger::Initialize(LogLevel MinimumLogLevel, std::wstring FilePath, int BufferThreshold)
{
	mMinimumLogLevel = MinimumLogLevel;
	mFilePath = FilePath;
	mBufferThreshold = BufferThreshold;

	mFile.open(mFilePath);
	if (!mFile.is_open())
	{
		MessageBoxW(NULL, L"Couldn't open log file!", L"Engine Warning", MB_OK);
	}
	else
		mFile.close();
}

bool Logger::LogMessage(std::wstring Message, LogLevel Level)
{
	if(Level < this->mMinimumLogLevel)
	{
		return false;
	}

	//For future reference, remember to use L"string" rather than "string"
	//when working with Unicode. (that's what I hate about it)
	//	- Kyle

	//TODO: explore wcout
	std::wstring MessageTypePrefix;
	switch(Level)
	{
	case LOGLEVEL_UNDEFINED:
		MessageTypePrefix = L"Undefined LOGLEVEL: ";
		break;
	case LOGLEVEL_CRITICAL:
		MessageTypePrefix = L"Critical Error: ";
		break;
	case LOGLEVEL_ERROR:
		MessageTypePrefix = L"Error: ";
		break;
	case LOGLEVEL_WARNING:
		MessageTypePrefix = L"Warning: ";
		break;
	case LOGLEVEL_NOTICE:
		MessageTypePrefix = L"Notice: ";
		break;
	case LOGLEVEL_INFO:
		MessageTypePrefix = L"Info: ";
		break;
	}

#ifdef _DEBUG
	std::wcout << MessageTypePrefix + Message + OS_LINE_ENDING;
#endif

	mBufferCount++;
	mBuffer += MessageTypePrefix + Message + OS_LINE_ENDING;

	if (mBufferCount >= mBufferThreshold)
		FlushBuffer();

	return true;
}

void Logger::FlushBuffer()
{
	mFile.open(mFilePath, std::ios::app);
	if (!mFile.is_open())
	{
		return;
	}
	mFile << mBuffer << std::endl;
	mFile.close();

	mBufferCount = 0;
	mBuffer.clear();
}

Logger & Logger::operator << (const std::wstring &Message)
{
	mBuffer += Message;
	return *this;
}

Logger & Logger::operator << (const int &Message)
{
	std::wstringstream ss; ss << Message;
	mBuffer += ss.str();
	return *this;
}

Logger & Logger::operator << (const real &Message)
{
	std::wstringstream ss; ss << Message;
	mBuffer += ss.str();
	return *this;
}

INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

bool Logger::PromptUploadPermission(Window* window)
{
	HWND handle = NULL;
	if (window != 0)
		handle = (HWND)window->GetWindowPointer();
	INT_PTR result = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_UPLOADPERMISSION), handle, DialogProc);
	if (result == IDYES)
	{
		mCanUploadData = true;
		return true;
	}
	mCanUploadData = false;
	return false;
}

INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_CLOSE:
		{
			EndDialog(hWnd, IDNO);
			break;
		}
	case WM_COMMAND:
		{
			switch (LOWORD(wParam))
			{
			case IDYES:
				EndDialog(hWnd, IDYES);
				break;
			case IDNO:
				EndDialog(hWnd, IDNO);
				break;
			}
			break;
		}
	}
	return 0;
}

}